#include "s7String.h"
#include <string.h>

// 初始化函数
void S7String_Init(char* str, unsigned char maxLen) {
  if(str == NULL)
    return;
  str[0] = maxLen;            // MaxLen
  str[1] = 0;                 // ActualLen
  memset(&str[2], 0, maxLen); // 清空内容
}

// 字符串赋值
void S7String_Set(char* str, const char* src) {
  if(str == NULL || src == NULL)
    return;

  uint8_t maxLen = (uint8_t) str[0];
  uint8_t srcLen = (uint8_t) strlen(src);

  if(srcLen > maxLen)
    srcLen = maxLen;

  str[1] = srcLen;
  memcpy(&str[2], src, srcLen);

  // 补一个\0，确保在调试时printf("%s", &str[2])不会越界（不影响功能）
  if(srcLen < maxLen)
    str[2 + srcLen] = '\0';
  else
    // NOTE 此处需要修改
    str[2 + maxLen - 1] = '\0'; // 最后一字节保底
}

/// 读取字符串：返回以\0结尾的标准C字符串指针
const char* get_cstring(const char* str) {
  return &str[2];
}

/// 获取实际长度
uint8_t get_string_act_len(const char* str) {
  return (uint8_t) str[1];
}
/// 获取最大长度
uint8_t get_string_max_len(const char* str) {
  return (uint8_t) str[0];
}

// 判断两个字符串是否相等
Bool S7String_Equals(const char* s1, const char* s2) {
  if(s1 == NULL || s2 == NULL)
    return false;

  uint8_t len1 = (uint8_t) s1[1];
  uint8_t len2 = (uint8_t) s2[1];

  if(len1 != len2)
    return false;

  for(uint8_t i = 0; i < len1; ++i) {
    if((unsigned char) s1[2 + i] != (unsigned char) s2[2 + i])
      return false;
  }

  return true;
}

/// 创建一个 S7 格式字符串，返回 char* 指针（结构为 MaxLen + ActualLen + Data）
const char* S7String_Create(const char* cstr) {
  static char s7buf[1 + 1 + 254]; // MaxLen + ActualLen + Data

  s7buf[0] = 254; // MaxLen
  if(cstr == NULL) {
    s7buf[1] = 0;
    return s7buf;
  }

  size_t len = strlen(cstr);
  if(len > 254)
    len = 254;

  s7buf[1] = (uint8_t) len;     // ActualLen
  memset(&s7buf[2], 0, 254);    // 清空旧数据
  memcpy(&s7buf[2], cstr, len); // 拷贝数据

  return s7buf;
}

/// <summary>
/// 安全地拷贝西门子风格的 S7 字符数组（char[n]）
/// 等价于博图 String[n]，确保拷贝不越界并合法结束
/// </summary>
/// <param name="dest">目标 char 数组指针</param>
/// <param name="destSize">目标数组大小（字节）</param>
/// <param name="src">源字符串（必须以 \0 结尾）</param>
void S7String_Copy(char* dest, uint8_t destSize, const char* src) {
  if(dest == NULL || src == NULL || destSize == 0)
    return;

  size_t i = 0;
  for(; i < destSize - 1 && src[i] != '\0'; ++i) {
    dest[i] = src[i];
  }

  // 确保以 \0 结尾，即使源字符串过长
  dest[i] = '\0';
}

int get_bit_value(const void* ptr, uint8_t byteLength, uint16_t bit_pos) {
  if(ptr == NULL || byteLength == 0)
    return 0; // 容错
  if(bit_pos >= (uint16_t) byteLength * 8)
    return 0; // 越界保护

  const uint8_t* bytes = (const uint8_t*) ptr;

  // 按大端逻辑计算位位置
  //  uint16_t total_bits      = (uint16_t) byteLength * 8;
  //  uint16_t reverse_bit_pos = total_bits - 1 - bit_pos;

  //  uint8_t byte_index = reverse_bit_pos / 8;
  //  uint8_t bit_index  = reverse_bit_pos % 8;
  uint8_t byte_index = bit_pos / 8;
  uint8_t bit_index  = bit_pos % 8;
  return (bytes[byte_index] >> bit_index) & 0x01;
}

void set_bit_value(void* ptr, uint8_t byteLength, uint16_t bit_pos, int value) {
  if(ptr == NULL || byteLength == 0)
    return; // 容错
  if(bit_pos >= (uint16_t) byteLength * 8)
    return; // 越界保护

  uint8_t* bytes = (uint8_t*) ptr;

  // 按大端逻辑计算位位置
  //  uint16_t total_bits      = (uint16_t) byteLength * 8;
  //  uint16_t reverse_bit_pos = total_bits - 1 - bit_pos;

  //  uint8_t byte_index = reverse_bit_pos / 8;
  //  uint8_t bit_index  = reverse_bit_pos % 8;
  uint8_t byte_index = bit_pos / 8;
  uint8_t bit_index  = bit_pos % 8;
  uint8_t mask       = 1 << bit_index;
  if(value)
    bytes[byte_index] |= mask;
  else
    bytes[byte_index] &= ~mask;
}
